package cloud.keveri.gateway.plugin.response;

import cloud.keveri.base.ErrorCode;
import cloud.keveri.gateway.plugin.api.KeveriPlugin;
import cloud.keveri.gateway.plugin.api.KeveriPluginChain;
import cloud.keveri.gateway.plugin.api.support.WebFluxResultUtils;
import com.alibaba.fastjson2.JSON;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Objects;

import static cloud.keveri.gateway.plugin.api.GatewayPluginErrorCodeConstants.RESPONSE_EXTRACT_ERROR;
import static cloud.keveri.gateway.plugin.base.def.Const.*;

/**
 * <p>
 * 作者：沈自在
 **/
public class ResponsePlugin implements KeveriPlugin {

    @Override
    public int getOrder() {
        return PLUGIN_RESPONSE_ORDER;
    }

    /**
     *
     */
    @Override
    public Mono<Void> process(ServerWebExchange exchange, KeveriPluginChain chain) {
        return chain.execute(exchange).then(Mono.defer(() -> processResponse(exchange)));
    }

    /**
     *
     */
    private Mono<Void> processResponse(ServerWebExchange exchange) {
        Object errFlag = exchange.getAttribute(ERROR_FLAG);
        if (Objects.nonNull(errFlag)) {
            return handleErrorResponse(exchange, errFlag);
        }

        Object result = exchange.getAttribute(RPC_RESULT);
        if (Objects.isNull(result)) {
            return WebFluxResultUtils.error(exchange, RESPONSE_EXTRACT_ERROR);
        }

        return handleSuccessResponse(exchange, result);
    }

    /**
     *
     */
    private Mono<Void> handleErrorResponse(ServerWebExchange exchange, Object errFlag) {
        ErrorCode errorCode = JSON.parseObject(String.valueOf(errFlag), ErrorCode.class);
        Mono<Void> responseMono = WebFluxResultUtils.error(exchange, errorCode);
        exchange.getAttributes().put(RESPONSE_MONO, responseMono);
        return responseMono;
    }

    /**
     *
     */
    private Mono<Void> handleSuccessResponse(ServerWebExchange exchange, Object result) {
        Mono<Void> responseMono = WebFluxResultUtils.success(exchange, result);
        exchange.getAttributes().put(RESPONSE_MONO, responseMono);
        return responseMono;
    }
}